﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Meta.Numerics.Statistics.Distributions;

namespace ExcelAddIn1
{
    /**
     * Implementation of a dependent (paired), two-sided T-test.
     */
    class Test_T_dependent_2S : Test
    {
        public Test_T_dependent_2S(DataContainer data)
        {
            this.data = data;
            res = new List<String>();
        }

        public override string GetInfo()
        {
            String s = "Performs a Two-sided paired Student's T-test to check for significant differences between two datasets. ";
            s += "The test requires that the datasets are normally distributed, have equal variances and are dependent.";
            return s;
        }

        public override void RunTest()
        {
            res.Add("Two-sided paired T-test");

            //Error check
            if (data.GetNoSets() != 2)
            {
                res.Add("Two datasets is required!");
                return;
            }

            //Get data sets
            DataSet d1 = data.GetDataSet(0);
            DataSet d2 = data.GetDataSet(1);
            int n = d1.GetN();

            //Error check 2
            if (d1.GetN() != d2.GetN())
            {
                res.Add("Both datasets must have equal sample sizes!");
                return;
            }

            //Calculate the differences and squared differences
            double sumDiff = 0;
            double sumDiff2 = 0;
            for (int i = 0; i < n; i++)
            {
                double diff = d2.GetValue(i) - d1.GetValue(i);
                double diff2 = Math.Pow(diff, 2);

                sumDiff += diff;
                sumDiff2 += diff2;
            }

            //Calculate standard deviation of the differences
            double s = Math.Sqrt((sumDiff2 - Math.Pow(sumDiff, 2) / (double)n) / (double)(n - 1));

            //Calculate mean difference in samples
            double dmean = sumDiff / (double)n;

            //Calcualte T-score
            double T = (dmean - assumedMeanDiff) / (s / Math.Sqrt(n));

            //Get Critical T
            double DF = (double)(n - 1);
            StudentDistribution tdist = new StudentDistribution(DF);
            double TcLow = tdist.InverseLeftProbability(alpha / 2.0);
            double TcHigh = tdist.InverseRightProbability(alpha / 2.0);

            //Calculate P-value
            double p = tdist.RightProbability(T) * 2.0;
            
            //Results
            res.Add(";" + d1.GetName() + ";" + d2.GetName() + ";-");
            res.Add("N;" + d1.GetN() + ";" + d2.GetN() + ";-");
            res.Add("Mean;" + d1.GetMean().ToString("F2") + ";" + d2.GetMean().ToString("F2"));
            res.Add("StDev;" + d1.GetStDev().ToString("F2") + ";" + d2.GetStDev().ToString("F2"));
            res.Add("DoF;" + (int)DF);
            res.Add("α;" + alpha + ";;-");
            res.Add("P-value;" + p.ToString("F3"));
            if (assumedMeanDiff != 0.0)
            {
                res.Add("Diff in means;" + assumedMeanDiff.ToString("F2"));
            }
            res.Add("T-score;" + T.ToString("F2"));
            res.Add("T-crit;" + TcHigh.ToString("F2"));
            if (T < TcLow || T > TcHigh)
            {
                res.Add("Result;Significant difference at level " + p.ToString("F3"));
            }
            else
            {
                res.Add("Result;No difference (significance level " + p.ToString("F3") + ")");
            }
            res.Add(";;;-");
        }
    }
}
